//! This is a simple example of 
//! 1. create_signal + 闭包
//! 2. create_resource + async fn
//! 3. #[server("SendNortify","/api")]
//! 4. create_action + async fn.
//! 5. Await 组件
//! 
use leptos::*;
use serde::*;
use chrono::prelude::*;
use leptos_meta::Title;
// use leptos::{html::Input, *};
use thiserror::Error;
use anyhow::Result;
use reqwest::header::HeaderMap;


#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Cat {
    url: String,
}

#[derive(Error, Clone, Debug)]
pub enum CatError {
    #[error("Please request more than zero cats.")]
    NonZeroCats,
}

type CatCount = usize;

async fn fetch_cats(count: CatCount) -> Result<Vec<String>> {
    let images = vec!["SR509","SA509","AP510","rb2509","hc2509"];
    if count > 0 {     
        let mut res = vec!["http://8.155.160.209:9994/yee/static/out/SR509.png".to_owned()];
        for ii in 1..count {
            let s = format!("http://8.155.160.209:9994/yee/static/out/{}.png",  images[ ii%images.len()]  );            
            res.push( s );
        }
        Ok(res)
    } else {
        Err(CatError::NonZeroCats)?
    }
}

#[component]
pub fn Home() -> impl IntoView {
    
    let (cat_count, set_cat_count) = create_signal(1);
    //let (cats, set_cats) = create_signal(vec!["https://www.lengsh.cn/loong/middle/SR501.png?1728880403".to_owned(),"https://www.lengsh.cn/loong/middle/SR501.png?1728880403".to_owned()]); //  move || fetch_cats(cat_count.get()).await.unwrap();
    let async_data = create_resource(
        move || cat_count.get(),
        // 每次 `count` 发生变化时，这都会运行
        |value| async move {
       //     logging::log!("从 API 加载数据");
            fetch_cats(value).await.unwrap()
        },
    );

    let fallback = move |errors| {       
        let s = format!("{:?}", errors);
        view! {
            <div class="error">
                <h2>"Error"</h2>
                <ul> {s} </ul>
            </div>
        }
    };

    let add_msg_action = create_action(|input: &String| {
        let input = input.to_owned();
        async move { send_notify(input).await }
    });

    // let spreadable = style(("background-color", "AliceBlue"));
    view! {
        <Title text="Home Page" />
        <div>
            <label>
                "How many cats would you like?"
                <input
                    type="number"
                    prop:value=move || cat_count.get().to_string()       
                    on:input=move |ev| {
                        let val = event_target_value(&ev);
                        let count: CatCount = val.parse().unwrap_or(1);
                        set_cat_count.set(count);              
                    }           
                />

            </label>

            <Await
                // `future` 提供要解析的 `Future`
                future=|| fetch_monkeys(3)
                // 数据绑定到你提供的任何变量名
                let:data
            >
                // 你通过引用接收数据，并可以在此处在你的视图中使用它
                <p>{*data} " little monkeys, jumping on the bed."</p>
            </Await>
            <button on:click=move |_| add_msg_action.dispatch("hello".to_owned())>
                "send feishu notify with create_action"
            </button>        
            <Transition fallback=|| view! { <div>"Loading..."</div> } >
                <ErrorBoundary fallback>
                <div> "no move:" { cat_count.get().to_string() } " cats"                       
                </div>
                    <div> {
                        move || {
                            let c = cat_count.get().to_string();
                            view! {
                                <p>"You want " {c} " cats"</p>
                            }
                        }
                    }                        
                    </div>
                    <ul>
                        {                           
                           move || {                
                            let cats = if let Some(cats) = async_data.get() {
                                cats
                            }else {
                                vec![]
                            };
                            cats.into_iter().map(|s| {
                                            view! {
                                                <li>
                                                    <img src=s.clone() width="200px" />
                                                </li>
                                            }
                                        })
                                        .collect::<Vec<_>>()                                                      
                      
                            }
                        }
                    </ul>
                </ErrorBoundary>
            </Transition>
        </div>
    }
    
}


async fn fetch_monkeys(monkey: i32) -> i32 {
    // 也许这不需要是异步的
    monkey * 2
}

#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq )]
pub struct SimpleTask {         
    #[serde(default)]
    pub count: i32,
    #[serde(default)]    
    pub stamp: String,
}

#[server(AddTodo, "/api")]
pub async fn api_task(title: String) -> Result<SimpleTask, ServerFnError> {

    let now = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();    
    logging::log!("Adding todo {}, mybe get from db..., t = {}", title, &now);
	let t = SimpleTask{stamp:now, count:100};
    Ok(t)
}

#[server(SendNofity, "/api")]
pub async fn send_notify(msg: String) -> Result<(), ServerFnError> {
    logging::log!("[server] send notify: {}", msg);
    let _r = feishu_notify(msg).await;
    Ok(())
}
    
/** 
method = 'https://www.mark.lengsh.cn/xman/sendmessage'
headers = {'Content-Type': 'application/json', "Authorization":"Bearer xman"
payload = {'recv_id':recv_id, 'recv_type':recv_type, 'content': content,'msg_type': msg_type}
r = requests.post(method,  data =json.dumps(payload), headers=headers) 
*/ 
#[derive(Deserialize, Default, Debug, Serialize, Clone)]
pub struct Notify {
    #[serde(default)]
    pub recv_id: String,
    #[serde(default)]
    pub recv_type: String,
    #[serde(default)]
    pub content: String,
    #[serde(default)]
    pub msg_type: String,
}
pub async fn feishu_notify(msg: String) -> Result<()> {    
    let chat_id = "oc_208983102250542d93cb4081935fc489";
    let client = reqwest::Client::new();
    let api = "https://www.lengsh.cn/xman/sendmessage";
    let mut headers = HeaderMap::new();
    headers.insert("Authorization", "Bearer xman".parse()?);
    headers.insert("Content-Type", "application/json; charset=utf-8".parse()?);
    // headers.insert("Access-Control-Allow-Origin", "http://192.168.2.100".parse()?);
    
    let notify = Notify { 
        recv_id: chat_id.to_string(),
        recv_type: "chat_id".to_string(),
        msg_type: "text".to_string(),
        content: msg,
    };      
            
    let _r = client
        .post(api)
        .headers(headers)
        .json(&notify)
        .send()
        .await?
        .text()
        .await?;
    
    return std::result::Result::Ok(());

}
   

